﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using VMDS.Business.Entities;
using VMDS.Business.Processes;
using VMDS.GUIClient.Helper;
using VMDS.GUIClient.Model;
using VMDS.GUIClient.ServiceReference;
using VMDS.Settings;

namespace VMDS.GUIClient.ViewModels
{
    class Screenshot
    {
        public BitmapImage Image { get; set; }
    }
    class DisplayVM:BaseViewModel
    {

        private BitmapImage _img;
        public BitmapImage ImagePath
        {
            get { return _img; } 
            set
            {
                _img = value; OnPropertyChanged(() => ImagePath); }
        }

        private VM _vm;
        public VM Vm
        {
            get { return _vm; }
            set { _vm = value;OnPropertyChanged(()=>Vm); }
        }


        private bool _stop=false;
        public bool Stop
        {
            get { return _stop; }
            set { _stop = value; OnPropertyChanged(() => Stop); OnPropertyChanged(() => IconVisible); }
        }
        public bool IconVisible
        {
            get { return !Stop; }
            set { Stop = !value;  }
        }

       
    }

    class VmLibraryViewModel:BaseViewModel
    {


        private bool _filByState;
        public bool FilterByState
        {
            get { return _filByState; }
            set { _filByState = value;
                OnPropertyChanged(() => FilterByState);
            }
        }

      
       public void ReloadVms()
       {
           ObservableCollection<VM> vms=new ObservableCollection<VM>(Repozitory.OnlineVms);
           foreach (var vm in Repozitory.OfflineVms)
           {
               if (vms.SingleOrDefault(x => x.Id == vm.Id) == null) vms.Add(vm);
           }
           ObservableCollection<DisplayVM> result=new ObservableCollection<DisplayVM>();
           foreach (VM vm in vms)
           {
               var v = new DisplayVM() {Vm = vm};
               SetIcon(v);
               v.Stop = Busy(v);
               result.Add(v);
           }
           var sorted = from vm in result orderby vm.Vm.Name ascending select vm;
                           ;
           VMs= new ObservableCollection<DisplayVM>(sorted.Where(x=>x.Vm.Visible));
       }

        bool online(DisplayVM cvm)
        {
            VM vm;
            if (cvm==null) return false;
            vm = cvm.Vm;
            if (vm != null)
                return Repozitory.OnlineVms.Any(x => x.Id == vm.Id);
            else return false;
        }

        bool offline(DisplayVM cvm)
        {
            VM vm;
            if (cvm == null) return false;
            vm = cvm.Vm;
            if (vm != null)
                return Repozitory.OfflineVms.Any(offlineVm => offlineVm.Id == vm.Id);
            else return false;
        }

        bool Busy(DisplayVM cvm)
        {
            VM vm;
            if (cvm == null) return false;
            vm = cvm.Vm;
            var result= OperationsViewModel.Instance.IsBusy(vm);
            if (result)
            {
                LockMessage = "Идет установка. Операции недоступны";
                cvm.Stop = true;
            }
            else { LockMessage = "";
                cvm.Stop = false;
            }
            return result;
        }

        public bool CanSetup
        {
            get { return (online(_currVm)&&!Busy(_currVm)); }
        }

        public bool CanStart
        {
            get { return (offline(_currVm) && !Busy(_currVm)); }
        }

        public bool CanReInstall
        {
            get { return CanStart && CanSetup; }
        }


        private ObservableCollection<DisplayVM> _vms;
        public ObservableCollection<DisplayVM> VMs
        {
            get
            {
               
                return _vms;
            }
            set { _vms = value;OnPropertyChanged(()=>VMs); }
        }

        private ObservableCollection<Image> _imgs;
        public ObservableCollection<Image> Images
        {
            get { return _imgs; }
            set { _imgs = value;OnPropertyChanged(()=>Images); }
        }

        private BackgroundWorker scrupdater;
        private Thread _t;
        void updScr()
        {
           /* if (scrupdater==null)
            scrupdater = new BackgroundWorker();
            if (scrupdater.IsBusy) {_t.Abort(); }
            scrupdater.DoWork += new DoWorkEventHandler(scrupdater_DoWork);
            scrupdater.RunWorkerAsync();*/
            GetScreenshots(CurrentVM);
        }

        void scrupdater_DoWork(object sender, DoWorkEventArgs e)
        {
            _t = Thread.CurrentThread;
            GetScreenshots(CurrentVM);
        }

        private string Share;
        void SetIcon(DisplayVM vm)
        {
            if (vm == null) return;
            string screendir = "";
             
            if (online(vm)) try
                {
                    screendir = Share + "\\vm\\" + vm.Vm.Name;

                }
                catch { }
            if (offline(vm)) try
                {
                    screendir = new ClientConfiguration(@"d:\virtual\data\config.ini").LocalStorage + "vm\\" + vm.Vm.Name;
                }
                catch { }

            if (!Directory.Exists(screendir)) return;
            var img = Directory.EnumerateFiles(screendir, "icon.*").FirstOrDefault();
            if (img != null)
            {
                
                vm.ImagePath = FileToBitmap(img);
            }

        }

        BitmapImage FileToBitmap(string file)
        {
            MemoryStream byteStream = new MemoryStream(FileToByteArray(file));
            BitmapImage image = new BitmapImage();
            image.BeginInit();
            image.StreamSource = byteStream;
            image.EndInit();
            return image;
        }

        public byte[] FileToByteArray(string _FileName)
        {
            byte[] _Buffer = null;

            try
            {
                // Open file for reading
                System.IO.FileStream _FileStream = new System.IO.FileStream(_FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);

                // attach filestream to binary reader
                System.IO.BinaryReader _BinaryReader = new System.IO.BinaryReader(_FileStream);

                // get total byte length of the file
                long _TotalBytes = new System.IO.FileInfo(_FileName).Length;

                // read entire file into buffer
                _Buffer = _BinaryReader.ReadBytes((Int32)_TotalBytes);

                // close file reader
                _FileStream.Close();
                _FileStream.Dispose();
                _BinaryReader.Close();
            }
            catch (Exception _Exception)
            {
                
            }

            return _Buffer;
        }
       

         void GetScreenshots(DisplayVM vm)
         {
             if (vm == null) return;
             var cfg = new ClientConfiguration(@"d:\virtual\data\config.ini");
             string screendir="";
             if (online(vm)) try
                 {
                     //screendir = ServiceLocator.MainService.GetShareUNC() + "\\vm\\"+vm.Vm.Name;
                     screendir = cfg.LocalStorage + "cache\\screenshots\\"+vm.Vm.Name;
                 }
                 catch { }
             if (offline(vm)) try
             {
                 screendir = cfg.LocalStorage + "vm\\" + vm.Vm.Name;
             }
                 catch { }

             List<string> sp = new List<string>() {"*.jpg", "*.gif", "*.png", "*.bmp"};
             var icon = screendir + "\\icon.png";
             ScreenShots = new ObservableCollection<Screenshot>();
             if (File.Exists(icon))
                 Dispatcher.FromThread(thread).
                     Invoke(new Action(() => ScreenShots.Add(new Screenshot() {Image = FileToBitmap(icon)})), DispatcherPriority.Render);
            
             
             if (!Directory.Exists(screendir)) return;
             
             foreach (string s in sp)
             {
                 foreach (var img in Directory.EnumerateFiles(screendir, s))
                 {
                     if (img == screendir + "\\icon.png") continue;
                     Screenshot scr = new Screenshot() {Image = FileToBitmap(img)};
                     
                     Dispatcher.FromThread(thread).
                    Invoke(new Action(() => ScreenShots.Add(scr)), DispatcherPriority.Render);
            

                 }
             }
             OnPropertyChanged(() => ScreenShots);
             OnPropertyChanged(() => CurrentVM);
         }
        void Reflesh()
        {
            OnPropertyChanged(() => CurrentVM);
            OnPropertyChanged(() => CanSetup);
            OnPropertyChanged(() => CanStart);
            OnPropertyChanged(() => CanReInstall);
            OnPropertyChanged(() => StartVm);
            OnPropertyChanged(() => SetupVm);
        }
        private DisplayVM _currVm;
        public DisplayVM CurrentVM 
        { 
            get { return _currVm; } 
            set 
            {
                _currVm = value;
                updScr();
                Reflesh();
            }
        }

        

        private ObservableCollection<Screenshot> _scr;
        public ObservableCollection<Screenshot> ScreenShots
        {
            get { return _scr; }
            set { _scr = value;
                OnPropertyChanged(() => ScreenShots);
            }
        }

        private string _lmsg;
        public string LockMessage
        {
            get { return _lmsg; }
            set { _lmsg = value;OnPropertyChanged(()=>LockMessage); }
        }

        public ICommand GotoOperations
        {
            get { return new BaseCommand(() =>
                                             {
                                                 var m = CrossWindowConnector.MainView;
                                                 (m as MainWindowViewModel).NavigationLink =
                                                     CrossWindowConnector.Pages.Operations;
                                             }); }
        }

        public ICommand StartVm { get { return new BaseCommand(StartCurrentVm, () => CanStart); } }
        private void StartCurrentVm()
        {
            StartDialogViewModel.Instance.VmName = CurrentVM.Vm.Name;
            StartDialogViewModel.Instance.Visible = true;
        }

        public ICommand SetupVm { get { return new BaseCommand(SetupCurrentVm, () => CanSetup); } }

      

        void SetupCurrentVm()
        {
            OperationsViewModel.Instance.Setup(CurrentVM.Vm);
            OperationsViewModel.Instance.Operations.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Operations_CollectionChanged);
            Reflesh();
        }

        void Operations_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            foreach (var displayVm in VMs)
            {
                Busy(displayVm);
            }
            Repozitory.OfflineVms = ServiceLocator.ClientService.GetOfflineVMs();
            Reflesh();
        }


        private Thread thread;
        
        public VmLibraryViewModel()
        {
            CrossWindowConnector.VmLib = this;
            thread = Thread.CurrentThread;
            try
            {
                Share = ServiceLocator.MainService.GetShareUNC();
            }
            catch 
            {
            }
            ReloadVms();
        }
    }
}
